package xm.net
{
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	
	/**
	 * MultipartUploader 클래스에서 사용되는 멀티파트 폼 데이터(바이트어레이)
	 * @author kjhbond
	 */	
	public class FormData
	{
		
		
		/**
		 * 이상한 값. sadjlfhhlasdjhfalskdjhf 
		 */		
		public var main_boundary : String;
		
		
		
		private var _variablesList:Array;
		private var _filesList:Array;
		
		
		/**
		 * constructor
		 */		
		public function FormData()
		{
			main_boundary = getBoundary();
			_variablesList = [];
			_filesList = [];
		}
		
		
		/**
		 * 변수 추가 
		 * @param variable_name
		 * @param data
		 * 
		 */		
		public function addVariable(variable_name:String, data:String):void
		{
			_variablesList.push( variable_name );
			_variablesList.push( data );
		}
		
		
		
		/**
		 * 바이트 어레이로 인코딩된 파일추가.
		 * @param file_name
		 * @param data
		 */		
		public function addFileOnByteArray( file_name:String, data:ByteArray ):void
		{
			
			_filesList.push( file_name );
			_filesList.push( data );
		}
		
		
		
		/**
		 * add된 데이터와, 파일을 ByteArray로 인코딩하여 반환하는 메서드.
		 * @return 
		 * 
		 */		
		public function getPostData():ByteArray
		{
			
			var i:int, 
				len:int,
				_variable_name:String,
				_variable : String, 
				_file_name:String,
				_data:ByteArray,
				bytes:ByteArray,
				isMultiFile : Boolean=false;
			
				
			// 바이트 생성 및 헤더구문 초기화
			bytes = new ByteArray();
			bytes.endian = Endian.BIG_ENDIAN;
			
			
			// 변수 추가.
			i=0;
			len = _variablesList.length;
			
			while( i<len )
			{
				_variable_name = _variablesList[ i ];
				_variable = _variablesList[ i+1 ];
				
				bytes = writeDoubleDash( bytes );
				bytes = writeBoundary(bytes, main_boundary);
				bytes = writeLineBreak(bytes);
				bytes = writeString(bytes, 'Content-Disposition: form-data; name="' + _variable_name + '"');
				bytes = writeLineBreak(bytes);
				bytes = writeLineBreak(bytes);
				bytes.writeUTFBytes( _variable );
				bytes = writeLineBreak(bytes);
				
				i += 2;
			}
			
			
			
			
			// 파일 추가.
			i=0;
			len=_filesList.length;
			if( _filesList.length > 2 ) isMultiFile = true;
			while( i<len )
			{
				_file_name = _filesList[ i ];
				_data = _filesList[ i+1 ];
				_variable_name = (isMultiFile) ? "fileData[]" : "fileData";
				
				bytes = writeDoubleDash( bytes );
				bytes = writeBoundary(bytes, main_boundary);
				bytes = writeLineBreak(bytes);
				bytes = writeString(bytes, 'Content-Disposition: form-data; name=' + _variable_name + '; filename="');
				bytes.writeUTFBytes(_file_name);
				bytes = writeQuotationMark( bytes );
				bytes = writeLineBreak(bytes);
				bytes = writeString(bytes, 'Content-Type: application/octet-stream');
				bytes = writeLineBreak(bytes);
				bytes = writeLineBreak(bytes);
				bytes.writeBytes(_data, 0, _data.length);
				bytes = writeLineBreak(bytes);
				
				i += 2;
			}
			
			
			// 바이트 헤더구문 닫기.
//			bytes = writeLineBreak(bytes);
			bytes = writeDoubleDash(bytes);
			bytes = writeBoundary(bytes, main_boundary);
			bytes = writeDoubleDash(bytes);
			
			return bytes;
		}
		
		
		
		/**
		 * destroy
		 */		
		public function destroy():void
		{
			this.main_boundary = null;
			_filesList = null;
			_variablesList = null;
		}
		
		
		
		
		
		
		/**
		 * 
		 * @return asklfjhalskdfhlkashjfd 같은 이상한 문자열;;
		 */		
		protected function getBoundary():String
		{
			var _boundary : String = "";
			if(_boundary.length == 0)
			{
				for (var i:int = 0; i < 0x20; i++ )
				{
					_boundary += String.fromCharCode( int( 97 + Math.random() * 25 ) );
				}
			}
			
			return _boundary;
		}
		
		
		/**
		 * 바이너리에 문자열 쓰기
		 * @param bytes
		 * @param str
		 * @return 
		 * 
		 */		
		protected function writeString(bytes:ByteArray, str:String):ByteArray
		{
			for (var i:int = 0; i < str.length; i++ )
			{
				bytes.writeByte( str.charCodeAt( i ) );
			}
			
			return bytes
		}
		
		
		/**
		 * 바이너리에 바운더리 쓰기
		 * @param bytes
		 * @param _boundary
		 * @return 
		 * 
		 */		
		protected function writeBoundary(bytes:ByteArray, _boundary:String):ByteArray
		{
			bytes = writeString(bytes, _boundary);
			return bytes;
		}
		
		
		/**
		 * 바이너리에 라인 쓰기
		 * @param bytes
		 * @return 
		 * 
		 */		
		protected function writeLineBreak(bytes:ByteArray):ByteArray
		{
			bytes.writeShort(0x0d0a);
			return bytes;
		}
		
		
		
		/**
		 * 바이너리에 마크.
		 * @param bytes
		 * @return 
		 * 
		 */		
		protected function writeQuotationMark(bytes:ByteArray):ByteArray 
		{
			bytes.writeByte(0x22);
			return bytes;
		}
		
		/**
		 * 바이너리에 "--" 쓰기
		 * @param bytes
		 * @return 
		 */		
		protected function writeDoubleDash(bytes:ByteArray):ByteArray
		{
			bytes.writeShort(0x2d2d);
			return bytes;
		}
		
		
	}
}